/*********************************************************
 * File Name   : Observer.c
 * Author      : Elvis Wang
 * Mail        : huan.wang@ingenic.com
 * Created Time: 2020-02-25 10:53
 ********************************************************/

#include <stdio.h>

typedef struct _observer Observer;
typedef struct _subject Subject;

struct _subject {
	int year;
	int month;
	int day;

	int observer_cnt;
	Observer *observer_list[8];
	int (*add_observer)(Observer *observer);
	int (*del_observer)(Observer *observer);
	int (*notify)(Subject *subjet);
};

struct _observer {
	Subject *subject;
	int (*update)(int year, int mouth, int day);
};

int DemoAddObserver(Observer *observer)
{
	if (!observer)
		return -1;

	Subject *subject = observer->subject;

	subject->observer_list[subject->observer_cnt] = observer;
	subject->observer_cnt++;

	return 0;
}

int DemoDelObserver(Observer *observer)
{
	if (!observer)
		return -1;

	Subject *subject = observer->subject;
	// do something
	subject->observer_cnt--;

	return 0;
}

int DemoNotify(Subject *subject)
{
	if (!subject)
		return -1;

	for (int i = 0; i < subject->observer_cnt; i++) {
		subject->observer_list[i]->update(subject->year, subject->month, subject->day);
	}

	return 0;
}

int update0(int year, int month, int day)
{
	printf("Hi Eami, Today is %d-%d-%d.\n", year, month, day);
	return 0;
}

int update1(int year, int month, int day)
{
	printf("Hi Kiki, Today is %d-%d-%d.\n", year, month, day);
	return 0;
}

int update2(int year, int month, int day)
{
	printf("Hi Vivi, Today is %d-%d-%d.\n", year, month, day);
	return 0;
}

int main()
{
	Subject subject;
	subject.add_observer = DemoAddObserver;
	subject.del_observer = DemoDelObserver;
	subject.notify = DemoNotify;
	subject.observer_cnt = 0;

	Observer observer0;
	Observer observer1;
	Observer observer2;
	observer0.subject = &subject;
	observer1.subject = &subject;
	observer2.subject = &subject;
	observer0.update = update0;
	observer1.update = update1;
	observer2.update = update2;

	subject.add_observer(&observer0);
	subject.add_observer(&observer1);
	subject.add_observer(&observer2);

	subject.year = 2018;
	subject.month = 9;
	subject.day = 20;
	subject.notify(&subject);
	printf("\n");

	subject.year = 2019;
	subject.month = 3;
	subject.day = 18;
	subject.notify(&subject);
	printf("\n");

	subject.year = 2020;
	subject.month = 2;
	subject.day = 25;
	subject.notify(&subject);

	return 0;
}
